<template>
  <div class="home-index-page w-1200">
    <div class="left-category">
      <ul>
        <li
          v-for="item in categoryOption"
          :key="item.value"
          :class="{ active: categoryValue === item.value }"
          @click="handleChangeCategory(item.value)"
        >
          <i :class="item.icon"></i>
          <span>{{ item.label }}</span>
        </li>
      </ul>
    </div>
    <div class="articlelist-content">
      <ul class="sort-type-ul">
        <li
          @click="handleSortList('new')"
          :class="{ active: sort === 'new' }">最新</li>
        <li
          @click="handleSortList('hot')"
          :class="{ active: sort === 'hot' }">最热</li>
      </ul>
      <div>
        <div
          v-if="requestLoading"
          style="padding: 20px 30px; background: #fff"
        >
          <a-skeleton active :title="{ width: 160 }" />
        </div>
        <div
          v-if="!pagination.list.length && !requestLoading"
          style="padding: 30px 0"
        >
          <a-empty
            description="暂无数据"
            :image="require('~/assets/images/nodata.png')"
          />
        </div>
        <div v-if="pagination.list.length && !requestLoading">
          <div
            v-for="item in pagination.list"
            :key="item.id"
            class="model"
            @click="openLink(item.id)"
          >
            <div class="l">
              <div class="user-info">
                <a-popover destroy-tooltip-on-hide>
                  <template slot="content">
                    <div class="user-content-popover">
                      <div class="top-info">
                        <div class="l">
                          <HeadAvatar :width="45" :height="45" :img="item.avatar" />
                        </div>
                        <div class="c">
                          <p class="nickname">
                            {{ item.nickname }}
                            <Level :level="calcLevelFromExp(item.exp)" />
                          </p>
                          <p class="job">{{ item.job || '- -' }}</p>
                        </div>
                      </div>
                      <div v-if="userInfo.id !== item.userId" class="center-operate">
                        <a-button
                          v-if="!item.isFocusAuthor"
                          type="primary"
                          size="small"
                          icon="user-add"
                          @click="updateUserFocus(true, item)"
                          >关注</a-button
                        >
                        <a-button
                          v-else
                          type="primary"
                          size="small"
                          icon="check"
                          @click="updateUserFocus(false, item)"
                          >已关注</a-button
                        >
                        <a-button
                          type="dashed"
                          icon="mail"
                          @click="handleImPerson(item.userId)"
                          >私信</a-button
                        >
                      </div>
                      <div class="bottom-statistic">
                        <div class="block">
                          <p>{{ item.foucsCounts }}</p>
                          <span>关注</span>
                        </div>
                        <div class="block">
                          <p>{{ item.fansCounts }}</p>
                          <span>粉丝</span>
                        </div>
                      </div>
                    </div>
                  </template>
                  <p @click.stop>
                    <nuxt-link target="_blank" :to="`/user/${item.userId}`">{{
                      item.nickname
                    }}</nuxt-link>
                  </p>
                </a-popover>
                <p>{{ cycleDate(item.createTime) }}</p>
                <p>
                  <em
                    v-for="itemName in item.tag.split(';')"
                    :key="itemName"
                    >{{ tagMap[itemName] || itemName }}</em
                  >
                  <em class="category-name">{{ categoryMap[item.category] }}</em>
                </p>
              </div>
              <p class="article-title">{{ item.articleTitle }}</p>
              <p class="article-desc">{{ item.description }}</p>
              <div class="a-num">
                <p>
                  <i class="ri-eye-line"></i>
                  <span v-if="item.viewCounts">{{ item.viewCounts | splitNumber }}</span>
                </p>
                <p
                  :class="{ 'is-liker': item.isLiker }"
                  @click.stop="isLikeArticle($event, item)"
                >
                  <i class="ri-thumb-up-line"></i>
                  <span v-if="item.likeCounts">{{ item.likeCounts }}</span>
                </p>
                <p>
                  <i class="ri-message-ai-3-line"></i><span v-if="item.commentCounts">{{
                    item.commentCounts
                  }}</span>
                </p>
              </div>
            </div>
            <div v-if="item.coverImage" class="r">
              <img :src="item.coverImage" alt="cover-image" />
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="right-message">
      <div class="tip">
        <div>
          <p>
            {{ getTimePeriod() }}好，
            {{ userInfo ? userInfo.nickname : '朋友' }}。
          </p>
          <a-button
            v-if="userInfo"
            :type="userInfo.hasSigned ? 'link' : 'primary'"
            @click="userHandleSignIn">{{ userInfo.hasSigned ? '已签到' : '签到' }}</a-button>
        </div>
        <span>愿您心情愉悦，笑口常开！</span>
      </div>
      <div>
        <div class="author-rank">
          <div class="title">
            <p>用户周榜</p>
          </div>
          <div class="rank-list">
            <div class="rank-list-item">
              <nuxt-link
                v-for="(item, index) in userRankList"
                :key="item.id"
                target="_blank"
                :to="`/user/${item.id}`"
                class="rank-list-item__block"
              >
                <em class="rank-no" :class="{ first: index === 0, second: index === 1, third: index === 2 }">{{ index + 1 }}</em>
                <HeadAvatar :width="32" :height="32" :img="item.avatar" />
                <div class="right-info">
                  <p>
                    <em>{{ item.nickname }}</em>
                    <Level :level="calcLevelFromExp(item.exp)" />
                  </p>
                  <span class="job">{{ item.job || '--' }}</span>
                </div>
              </nuxt-link>
            </div>
          </div>
        </div>
      </div>
      <div style="margin-top: 10px; position: sticky; top: 66px;">
        <SiteCopyRight />
      </div>
    </div>
  </div>
</template>

<script>
import { mapState } from 'vuex'
import { cycleDate, calcLevelFromExp, getTimePeriod } from '~/util'
import ScrollLoadEvent from '~/util/scrollLoadEvent'
import { tagMap, categoryMap, categoryOption } from '~/config/optionMap'
import SiteCopyRight from '~/components/SiteCopyRight'
export default {
  name: 'IndexPage',
  layout: 'BaseLayout',
  components: { SiteCopyRight },
  async asyncData ({ $axios }) {
    const [pageNo, pageSize] = [1, 10]
    try {
      const { data } = await $axios.get(`/gimishare/api/v1/articles?pageNo=${pageNo}&pageSize=${pageSize}&sort=new`)
      const { data: userRankList } = await $axios.get('/gimishare/api/v1/statistics/userrank?pageNo=1&pageSize=5')
      return {
        pagination: { ...data, pageSize },
        userRankList
      }
    } catch (error) {
      return {
        pagination: { list: [], pageNo: 1, total: 0, pageSize },
        userRankList: []
      }
    }
  },

  data () {
    return {
      tagMap,
      cycleDate,
      calcLevelFromExp,
      getTimePeriod,
      categoryMap,
      categoryOption: [
        { label: '我的关注', icon: 'ri-user-heart-line', value: 'focus' },
        { label: '综合', value: '', icon: 'ri-global-line' },
        ...categoryOption
      ],
      categoryValue: '',
      requestLoading: false,
      scrollLoadEvent: null,
      spinning: false,
      sort: 'new',
      signIng: false
    }
  },

  computed: {
    ...mapState({
      userInfo: (state) => state.userInfo
    })
  },

  created () {
    this.scrollLoadEvent = new ScrollLoadEvent(
      this.scrollLoadArticle.bind(this)
    )
    if (process.browser) {
      this.$nextTick(() => {
        this.scrollLoadEvent.bindScrollEvent()
      })
    }
  },

  methods: {
    /**
     * scroll load articleList
     */
    async scrollLoadArticle () {
      this.scrollLoadEvent.loadState = false
      try {
        this.pagination.pageNo++
        const { pageNo, pageSize } = this.pagination
        const { data } = await this.$axios.get(
          `/gimishare/api/v1/articles?pageNo=${pageNo}&pageSize=${pageSize}&category=${this.categoryValue}&sort=${this.sort}`
        )
        this.pagination.list.push(...data.list)
        if (pageNo >= Math.ceil(data.total / pageSize)) {
          this.scrollLoadEvent.loadState = false
        } else {
          this.scrollLoadEvent.loadState = true
        }
      } catch (error) {
        this.scrollLoadEvent.loadState = true
      } finally {
        this.requestLoading = false
      }
    },

    /**
     * article liker
     * @param { Object } articleItem
     */
    async isLikeArticle (_e, articleItem) {
      if (!this.userInfo) {
        return this.$store.commit('UPDATE_LOGIN_VISIBLE', true)
      }
      try {
        const API = articleItem.isLiker
          ? '/users/unagreearticle'
          : '/users/agreearticle'
        await this.$axios.get(
          `/gimishare/api/v1${API}?articleId=${articleItem.id}&uid=${articleItem.userId}`
        )
        if (articleItem.isLiker) {
          articleItem.likeCounts -= 1
        } else {
          articleItem.likeCounts += 1
        }
        articleItem.isLiker = !articleItem.isLiker
      } catch (error) {}
    },

    /**
     * user focus user
     * @param { Boolean } state true - focus  false - unfocus
     * @param { Object } userItem userinfo
     */
    async updateUserFocus (state, userItem) {
      if (!this.userInfo) {
        return this.$store.commit('UPDATE_LOGIN_VISIBLE', true)
      }
      try {
        const API = state ? '/users/focususer' : '/users/unfocususer'
        const focusId = userItem.userId
        await this.$axios.get(`/gimishare/api/v1${API}?focusId=${focusId}`)
        userItem.isFocusAuthor = !userItem.isFocusAuthor
      } catch (error) {
        console.log(error)
      }
    },

    handleImPerson (userId) {
      if (!this.userInfo) {
        return this.$store.commit('UPDATE_LOGIN_VISIBLE', true)
      }
      this.$router.push({
        path: '/notification/im',
        query: {
          participantId: userId
        }
      })
    },

    /**
     * update article category
     * @param { String } category
     */
    handleChangeCategory (category) {
      if (this.categoryValue === category) return
      this.categoryValue = category
      this.pagination.pageNo = 0
      this.pagination.list = []
      this.requestLoading = true
      this.scrollLoadArticle()
      document.documentElement.scrollTop = 0
    },

    handleSortList (type) {
      if (this.sort === type) return
      this.sort = type
      this.pagination.pageNo = 0
      this.pagination.list = []
      this.requestLoading = true
      this.scrollLoadArticle()
    },

    async userHandleSignIn () {
      if (this.signIng || this.userInfo?.hasSigned) return
      this.signIng = true
      try {
        await this.$axios.post('/gimishare/api/v1/users/sign-in')
        this.$store.commit('UPDATE_USER_INFO', {
          ...this.userInfo,
          hasSigned: true
        })
      } catch (e) {} finally {
        this.signIng = false
      }
    },

    openLink (id) {
      const { href } = this.$router.resolve(`/post/${id}`)
      window.open(href, '_blank')
    }
  },

  beforeDestroy () {
    this.scrollLoadEvent.removeScrollEvent()
  }
}
</script>

<style lang="less" scoped>
.fixed-article-category {
  position: fixed;
  top: 60px;
  left: 0;
  right: 0;
  border-bottom: 1px solid #f1f1f1;
  background: #fff;
  z-index: 999;
  .category-tab {
    height: 45px;
    display: flex;
    align-items: center;
    p {
      margin-right: 20px;
      cursor: pointer;
      &.active {
        color: var(--hover-primary-color);
      }
    }
  }
}
.home-index-page {
  margin-top: 12px;
  padding-bottom: 30px;
  display: flex;
  min-height: ~"calc(100vh - 60px)";
  .left-category {
    width: 188px;
    background: #fff;
    border-radius: 4px;
    position: fixed;
    top: 72px;
    min-height: 460px;
    ul {
      list-style: none;
      margin: 0;
      padding: 12px;
      li {
        height: 42px;
        cursor: pointer;
        padding: 0 12px;
        color: #515767;
        border-radius: 4px;
        display: flex;
        align-items: center;
        font-size: 14px;
        margin: 4px 0;
        &.active {
          background: var(--select-primary-color);
          color: var(--primary-color);
        }
        &:hover {
          background: var(--alaph-primary-color);
        }
        i {
          font-size: 18px;
          margin: 0 16px 0 6px;
          position: relative;
          top: 1px;
        }
      }
    }
  }
  .articlelist-content {
    margin-left: 200px;
    flex: 1;
    width: 0;
    border-radius: 4px 4px 0 0;
    .sort-type-ul {
      background: #fff;
      border-bottom: 1px solid #f1f1f190;
      list-style: none;
      display: flex;
      line-height: 42px;
      margin: 0;
      padding: 0 20px;
      border-radius: 4px 4px 0 0;
      li {
        margin-right: 30px;
        font-size: 15px;
        color: #515767;
        cursor: pointer;
        position: relative;
        &:hover {
          color: var(--primary-color);
        }
        &.active {
          color: #000;
          &:after {
            content: "";
            position: absolute;
            width: 12px;
            height: 3px;
            background: var(--primary-color);
            bottom: 0;
            left: 50%;
            transform: translateX(-50%);
            border-radius: 2px 2px 0 0 ;
          }
        }
      }
    }
  }
  .right-message {
    margin-left: 12px;
    width: 250px;
    .tip {
      background: #fff;
      padding: 16px 12px 16px 16px;
      border-radius: 4px;
      & > div {
        display: flex;
        align-items: center;
        p {
          flex: 1;
          color: #000;
          font-weight: 700;
          overflow: hidden;
          white-space: nowrap;
          text-overflow: ellipsis;
          font-size: 12px;
        }
        .ant-btn {
          padding: 0 12px;
          height: 30px;
          line-height: 28px;
          letter-spacing: 0;
          margin-left: 2px;
        }
      }
      span {
        font-size: 12px;
        display: inline-block;
        color: #000;
      }
    }
    .author-rank {
      background: #fff;
      margin-top: 10px;
      border-radius: 4px;
      .title {
        border-bottom: 1px solid #f1f1f190;
        padding: 12px 16px;
      }
      .rank-list {
        padding: 8px 0;
        .rank-list-item__block {
          display: flex;
          align-items: center;
          padding: 8px 2px 8px 16px;
          &:hover {
            background-color: hsla(0, 0%, 84.7%, 0.1);
          }
          .rank-no {
            width: 16px;
            line-height: 16px;
            text-align: center;
            display: block;
            font-style: normal;
            background: #ccc;
            border-radius: 4px;
            font-size: 11px;
            color: #4c4c4c;
            color: #fff;
            margin-right: 10px;
            font-weight: 600;
            &.first {
              background: #c91616;
            }
            &.second {
              background: #11c693;
            }
            &.third {
              background: #e17317;
            }
          }
          .right-info {
            width: 0;
            flex: 1;
            padding-left: 10px;
            p {
              display: flex;
              align-items: center;
              em {
                color: #333;
                overflow: hidden;
                white-space: nowrap;
                text-overflow: ellipsis;
                font-size: 13px;
                font-style: normal;
                max-width: ~"calc(100% - 36px)";
              }
            }
            .job {
              font-size: 12px;
              color: #999;
              display: block;
              overflow: hidden;
              white-space: nowrap;
              text-overflow: ellipsis;
            }
          }
        }
      }
    }
  }
}
</style>

<style lang="less">
.user-content-popover {
  width: 300px;
  padding: 20px;
  box-sizing: border-box;
  .top-info {
    display: flex;
    align-items: center;
    .c {
      flex: 1;
      padding: 0 10px;
      width: 0;
      p {
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
      }
      .nickname {
        color: #000;
        font-size: 16px;
        display: flex;
        align-items: center;
      }
      .job {
        font-size: 12px;
        color: #999;
      }
    }
  }
  .center-operate {
    display: flex;
    justify-content: space-between;
    margin-top: 15px;
    button {
      padding: 0;
      width: 110px;
    }
  }
  .bottom-statistic {
    border-top: 1px solid #f1f1f190;
    padding-top: 10px;
    display: flex;
    margin-top: 15px;
    .block {
      width: 50%;
      text-align: center;
      p {
        font-size: 18px;
        color: #000;
      }
      span {
        color: #999;
      }
    }
  }
}
</style>
